<?php
class Dmf_Csv
{
    private $_filename;
    
    private $_body;
    
    private $_split;
    
    private $_headers = array();
    
    private $_rows = array();
    
    public function __construct( $filename, $split = ';' )
    {
        if ( ! file_exists( $filename )  )
        {
            throw new Dmf_Exception_FileNotFound( 'CSV file: "' . $filename . '" could not be found.' );
        }
        
        $this->_filename = $filename;
        $this->_split = $split;
    }
    
    private function _getHeader( $header )
    {
        if ( is_numeric( $header ) )
        {
            return $header;
        }
        
        return array_search( $header, $this->_headers );
    }
    
    public function mapRows( $function )
    {
        $data = array();
        
        foreach( $this->_rows as $key => &$value )
        {
            $function( $this, $key, $value, $data );
        }
    }
    
    public function repeat( $from_column, $to_column )
    {
        $lines = explode( "\r\n", $this->getContent() );
        $data = array();
        $this->_body = '';
        $is_header = true;
        
        foreach( $lines as $line )
        {
            if ( $is_header )
            {
                $this->_body .= $line . "\n";
                $is_header = false;
                continue;
            }
            
            $parts = explode( $this->_split, $line );
            
            for ( $i = 0; $i < count( $parts ); $i++ )
            {
                if ( ! isset( $parts[ $i ] ) )
                {
                    continue;
                }
                
                if ( $i > $to_column || $i < $from_column )
                {
                    $this->_body .= $parts[ $i ] . $this->_split;
                }
                else
                {
                    $data[ $i ] = ( $parts[ $i ] == null ) ? ( isset( $data[ $i ] ) ? $data[ $i ] : null ) : $parts[ $i ];
                    
                    $this->_body .= $data[ $i ] . $this->_split;
                }
            }
            
            $this->_body .= "\n";
        }
    }
    
    public function replace( $replaces )
    {
        $this->_body = $this->getContent();
        
        foreach( $replaces as $from => $to )
        {
            if ( substr( $from, 0, 1 ) == '' && substr( $from, -1, strlen( $from ) ) == '/' )
            {
                $this->_body = preg_replace( $from, $to, $this->_body );
            }
            else
            {
                $this->_body = str_replace( $from, $to, $this->_body );
            }
        }
    }
    
    public function getContent()
    {
        return ( $this->_body == null ) ? file_get_contents( $this->_filename ) : $this->_body;
    }
    
    public function getHeaders()
    {
        return $this->_headers;
    }
    
    public function getRows()
    {
        return $this->_rows;
    }
    
    public function getRow( $row )
    {
        return isset( $this->_rows[ $row ] ) ? $this->_rows[ $row ] : null;
    }
    
    public function getColumn( $column )
    {
        $column = $this->_getHeader( $column );
        $data = array();
        
        foreach( $this->_rows as $row )
        {
            $data[] = isset( $row[ $column ] ) ? $row[ $column ] : null;
        }
        
        return $data;
    }
    
    public function read()
    {
        $lines = explode( "\n", $this->getContent() );
        
        $this->_headers = explode( $this->_split, $lines['0'] );
        
        unset( $lines['0'] );
        
        $lines = array_values( array_filter( $lines ) );
        
        foreach( $lines as $line )
        {
            if ( strlen( $line ) < 2 )
            {
                continue;
            }
            
            $this->_rows[] = explode( $this->_split, $line );
        }
        
        return true;
    }
}